home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / bchelp10.zip / TI445.ASC < prev    next >
Text File  |  1991-09-11  |  20KB  |  793 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.   PRODUCT  :  TURBO C                                NUMBER  :  445
  9.   VERSION  :  1.0 & 1.5
  10.        OS  :  DOS 2.X & 3.X
  11.      DATE  :  OCTOBER 5, 1988                         PAGE  :  1/13
  12.  
  13.     TITLE  :  INTERRUPT DRIVEN SERIAL COMMUNICATIONS
  14.  
  15.  
  16.  
  17.  
  18.   /*-------------------------------------------------------------*
  19.                               SERIAL.C
  20.  
  21.      The following code shows how to take advantage of some of
  22.      the Turbo C extensions to the C language to do asynchronous
  23.      communications without having to write supporting assembly-
  24.      language routines.
  25.  
  26.      This program bypasses the less-than-adequate PC BIOS com-
  27.      munications routines and installs a serial interrupt handler.
  28.      Direct access to PC hardware allows the program to run at
  29.      faster baud rates and eliminates the need for the main
  30.      program to continuously poll the serial port for data; thus,
  31.      implementing background communications.  Data that enters
  32.      the serial port is stored in a circular buffer.
  33.  
  34.      * Compile this program with Test Stack Overflow OFF.
  35.    *-------------------------------------------------------------*/
  36.   #include "serial.h"
  37.   #include <dos.h>
  38.   #include <conio.h>
  39.   #include <stdio.h>
  40.   #include <string.h>
  41.  
  42.   #define VERSION 0x0101
  43.  
  44.   #define FALSE           0
  45.   #define TRUE            (!FALSE)
  46.  
  47.   #define NOERROR         0       /* No error               */
  48.   #define BUFOVFL         1       /* Buffer overflowed      */
  49.  
  50.   #define ESC             0x1B    /* ASCII Escape character */
  51.   #define ASCII           0x007F  /* Mask ASCII characters  */
  52.   #define SBUFSIZ         0x4000  /* Serial buffer size     */
  53.  
  54.   int            SError          = NOERROR;
  55.   int            portbase        = 0;
  56.   void           interrupt(*oldvects[2])();
  57.  
  58.   static   char  ccbuf[SBUFSIZ];
  59.   unsigned int   startbuf        = 0;
  60.   unsigned int   endbuf          = 0;
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.   PRODUCT  :  TURBO C                                NUMBER  :  445
  75.   VERSION  :  1.0 & 1.5
  76.        OS  :  DOS 2.X & 3.X
  77.      DATE  :  OCTOBER 5, 1988                         PAGE  :  2/13
  78.  
  79.     TITLE  :  INTERRUPT DRIVEN SERIAL COMMUNICATIONS
  80.  
  81.  
  82.  
  83.  
  84.   /* Handle communications interrupts and put them in ccbuf */
  85.   void   interrupt com_int(void)
  86.   {
  87.       disable();
  88.       if ((inportb(portbase + IIR) & RX_MASK) == RX_ID)
  89.       {
  90.           if (((endbuf + 1) & SBUFSIZ - 1) == startbuf)
  91.               SError = BUFOVFL;
  92.  
  93.          ccbuf[endbuf++] = inportb(portbase + RXR);
  94.           endbuf &= SBUFSIZ - 1;
  95.       }
  96.  
  97.       /* Signal end of hardware interrupt */
  98.       outportb(ICR, EOI);
  99.       enable();
  100.   }
  101.  
  102.   /* Output a character to the serial port */
  103.   int    SerialOut(char x)
  104.   {
  105.       long int   timeout = 0x0000FFFFL;
  106.  
  107.       outportb(portbase + MCR,  MC_INT | DTR | RTS);
  108.  
  109.       /* Wait for Clear To Send from modem */
  110.       while ((inportb(portbase + MSR) & CTS) == 0)
  111.           if (!(--timeout))
  112.               return (-1);
  113.  
  114.       timeout = 0x0000FFFFL;
  115.  
  116.       /* Wait for transmitter to clear */
  117.       while ((inportb(portbase + LSR) & XMTRDY) == 0)
  118.           if (!(--timeout))
  119.               return (-1);
  120.  
  121.       disable();
  122.       outportb(portbase + TXR, x);
  123.       enable();
  124.  
  125.       return (0);
  126.   }
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.   PRODUCT  :  TURBO C                                NUMBER  :  445
  141.   VERSION  :  1.0 & 1.5
  142.        OS  :  DOS 2.X & 3.X
  143.      DATE  :  OCTOBER 5, 1988                         PAGE  :  3/13
  144.  
  145.     TITLE  :  INTERRUPT DRIVEN SERIAL COMMUNICATIONS
  146.  
  147.  
  148.  
  149.  
  150.   /* Output a string to the serial port */
  151.   void   SerialString(char *string)
  152.   {
  153.       while (*string)
  154.          SerialOut(*string++);
  155.   }
  156.  
  157.   /* This routine returns the current value in the buffer */
  158.   int    getccb(void)
  159.   {
  160.       int                res;
  161.  
  162.       if (endbuf == startbuf)
  163.           return (-1);
  164.  
  165.       res = (int) ccbuf[startbuf++];
  166.       startbuf %= SBUFSIZ;
  167.       return (res);
  168.   }
  169.  
  170.   /* Install our functions to handle communications */
  171.   void   setvects(void)
  172.   {
  173.       oldvects[0] = getvect(0x0B);
  174.       oldvects[1] = getvect(0x0C);
  175.       setvect(0x0B, com_int);
  176.       setvect(0x0C, com_int);
  177.   }
  178.  
  179.   /* Uninstall our vectors before exiting the program */
  180.   void   resvects(void)
  181.   {
  182.       setvect(0x0B, oldvects[0]);
  183.       setvect(0x0C, oldvects[1]);
  184.   }
  185.  
  186.   /* Turn on communications interrupts */
  187.   void   i_enable(int pnum)
  188.   {
  189.       int                c;
  190.  
  191.       disable();
  192.       c = inportb(portbase + MCR) | MC_INT;
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.   PRODUCT  :  TURBO C                                NUMBER  :  445
  207.   VERSION  :  1.0 & 1.5
  208.        OS  :  DOS 2.X & 3.X
  209.      DATE  :  OCTOBER 5, 1988                         PAGE  :  4/13
  210.  
  211.     TITLE  :  INTERRUPT DRIVEN SERIAL COMMUNICATIONS
  212.  
  213.  
  214.  
  215.  
  216.       outportb(portbase + MCR, c);
  217.       outportb(portbase + IER, RX_INT);
  218.       c = inportb(IMR) & (pnum == COM1 ? IRQ4 : IRQ3);
  219.       outportb(IMR, c);
  220.       enable();
  221.   }
  222.  
  223.   /* Turn off communications interrupts */
  224.   void   i_disable(void)
  225.   {
  226.       int                c;
  227.  
  228.       disable();
  229.       c = inportb(IMR) | ~IRQ3 | ~IRQ4;
  230.       outportb(IMR, c);
  231.       outportb(portbase + IER, 0);
  232.       c = inportb(portbase + MCR) & ~MC_INT;
  233.       outportb(portbase + MCR, c);
  234.       enable();
  235.   }
  236.  
  237.   /* Tell modem that we're ready to go */
  238.   void   comm_on(void)
  239.   {
  240.       int                c, pnum;
  241.  
  242.       pnum = (portbase == COM1BASE ? COM1 : COM2);
  243.       i_enable(pnum);
  244.       c = inportb(portbase + MCR) | DTR | RTS;
  245.       outportb(portbase + MCR, c);
  246.   }
  247.  
  248.   /* Go off-line */
  249.   void   comm_off(void)
  250.   {
  251.       i_disable();
  252.       outportb(portbase + MCR, 0);
  253.   }
  254.  
  255.   void   initserial(void)
  256.   {
  257.       endbuf = startbuf = 0;
  258.       setvects();
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.   PRODUCT  :  TURBO C                                NUMBER  :  445
  273.   VERSION  :  1.0 & 1.5
  274.        OS  :  DOS 2.X & 3.X
  275.      DATE  :  OCTOBER 5, 1988                         PAGE  :  5/13
  276.  
  277.     TITLE  :  INTERRUPT DRIVEN SERIAL COMMUNICATIONS
  278.  
  279.  
  280.  
  281.  
  282.       comm_on();
  283.   }
  284.  
  285.   void   closeserial(void)
  286.   {
  287.       comm_off();
  288.       resvects();
  289.   }
  290.  
  291.   /* Set the port number to use */
  292.   int    SetPort(int Port)
  293.   {
  294.       int                Offset, far *RS232_Addr;
  295.  
  296.       switch (Port)
  297.       { /* Sort out the base address */
  298.         case COM1 : Offset = 0x0000;
  299.                     break;
  300.         case COM2 : Offset = 0x0002;
  301.                     break;
  302.         default   : return (-1);
  303.       }
  304.  
  305.       RS232_Addr = MK_FP(0x0040, Offset);  /* Find out where the
  306.                                               port is.  */
  307.       if (*RS232_Addr == NULL) return (-1);/* If NULL, then port
  308.                                               not used. */
  309.       portbase = *RS232_Addr;              /* Otherwise, set
  310.                                               portbase. */
  311.  
  312.       return (0);
  313.   }
  314.  
  315.   /* This routine sets the speed; will accept funny baud rates. */
  316.   /* Setting the speed requires that the DLAB be set on.        */
  317.   int    SetSpeed(int Speed)
  318.   {
  319.       char                c;
  320.       int         divisor;
  321.  
  322.       if (Speed == 0)            /* Avoid divide by zero */
  323.           return (-1);
  324.       else
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.   PRODUCT  :  TURBO C                                NUMBER  :  445
  339.   VERSION  :  1.0 & 1.5
  340.        OS  :  DOS 2.X & 3.X
  341.      DATE  :  OCTOBER 5, 1988                         PAGE  :  6/13
  342.  
  343.     TITLE  :  INTERRUPT DRIVEN SERIAL COMMUNICATIONS
  344.  
  345.  
  346.  
  347.  
  348.           divisor = (int) (115200L/Speed);
  349.  
  350.       if (portbase == 0)
  351.           return (-1);
  352.  
  353.       disable();
  354.       c = inportb(portbase + LCR);
  355.       outportb(portbase + LCR, (c | 0x80)); /* Set DLAB   */
  356.       outportb(portbase + DLL, (divisor & 0x00FF));
  357.       outportb(portbase + DLH, ((divisor >> 8) & 0x00FF));
  358.       outportb(portbase + LCR, c);          /* Reset DLAB */
  359.       enable();
  360.  
  361.       return (0);
  362.   }
  363.  
  364.   /* Set other communications parameters */
  365.   int    SetOthers(int Parity, int Bits, int StopBit)
  366.   {
  367.       int                setting;